-- ======================================================================
-- Hell Logic Sniffer Addon 
-- 
-- Copyright 2013 Hell-Prototypes
--
-- http://www.hellprototypes.com/
-- ======================================================================

ModuleClass = "LS_DECODER"
ModuleName  = "CUSTOM"
ModuleAlias = "PIC ICSP"
ModuleParam1= "PGC CH."
ModuleParam2= "PGD CH."
ModuleTip   = [[
PIC ICSP 20bits Command Interface Decoder

Note: Only tested with "PIC18F14K50".
]]

--------------------------------------------------------------------------------
g_ch_num_PGD = 0
g_ch_num_PGC = 0

g_PGD_raw_data = {}
g_PGC_raw_data = {}

g_PGD_raw_data_index = 1
g_PGC_raw_data_index = 1

g_PGC_data_clocked_table = {}

g_byte_shift_mask = {0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
					 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000}

function main ()
    LS_API.DebugMsg("===ICSP_20Bits_Decoder.lua main function called===")
    -- param check
    if type(LS_PARAM) ~= "table" then
    	LS_API.MessageBox("<ICSP> LS_PARAM was not a table class")
		return
    end
    if #LS_PARAM ~= 6 then
    	LS_API.MessageBox("<ICSP> LS_PARAM's size must = 6, size = " .. #LS_PARAM)
    end
    
    g_ch_num_PGC = LS_PARAM[1]
    g_ch_num_PGD = LS_PARAM[2]

 	g_PGD_raw_data = LS_API.GetChannelData(g_ch_num_PGD)
	g_PGC_raw_data = LS_API.GetChannelData(g_ch_num_PGC)

	-- creat data clocked table
	creat_PGC_data_clocked_table()
	
	local byte_bit_index = 1
	local decode_out_index = 3
	local bit_index = 0
	local PGD_decode_out = {}
	local read_data = 0
	local point_list = {}
	local table_index = 1
	while table_index < #g_PGC_data_clocked_table do
		--LS_API.DebugMsg("<ICSP>table_index: " .. table_index)
		-- Read 4 bits command
		
		read_data, point_list = get_data(table_index, 4)
		table_index = table_index + 4
		if read_data < 0 then
			LS_API.DebugMsg("<ICSP> Read command error: " .. read_data)
			return
		end
		if not push_data_to_host(read_data, point_list) then
			return
		end

		-- Read 16 bits payload data
		read_data, point_list = get_data(table_index, 16)
		table_index = table_index + 16
		LS_API.DebugMsg("<ICSP> Read payload: " .. read_data)
		if read_data < 0 then
			LS_API.DebugMsg("<ICSP> Read payload error: " .. read_data)
			return
		end
		if not push_data_to_host(read_data, point_list) then
			return
		end
	end
end
--------------------------------------------------------------------------------
function get_data(base_index, length)
	local point_list = {}
	local PGD_byte_data = 0
	local bit_index = 0
	local l_index = 0
	local PGD_level = 0
	if length > 16 then
		return -1
	end
	for table_index = 1, length do
		l_index = base_index + table_index - 1
		if l_index >  #g_PGC_data_clocked_table then
			return -2
		end
		bit_index = g_PGC_data_clocked_table[l_index]
		point_list[table_index] = bit_index
		PGD_level = get_PGD_bit_level( bit_index )
		if PGD_level then
			PGD_byte_data = PGD_byte_data + g_byte_shift_mask[table_index]
		end
	end

	return PGD_byte_data, point_list
end
--------------------------------------------------------------------------------
function push_data_to_host(value, points)
	local decode_out = {}
	if type(points) ~= "table" then
		return false
	end

	decode_out[1] = points[1]
	decode_out[2] = value

	if type(points) == "table" then
		for i=1, #points do
			decode_out[i+2] = points[i]
		end
	end
	local ret = LS_API.DecodeElementPushBack(decode_out)
	if ret ~= 0 then
		LS_API.MessageBox("<ICSP> Fail to push decode result to host... ret =" .. ret)
		return false
	end
	
	return true
end
--------------------------------------------------------------------------------
-- OOD : get edge table, reserve for example - 2013.11.5
function creat_PGC_data_clocked_table()
	local clocked_count = 1
	local PGC_rawdata_index = 3
	while PGC_rawdata_index <= #g_PGC_raw_data do
		if g_PGC_raw_data[PGC_rawdata_index+1] == 0 then -- failling edge
			g_PGC_data_clocked_table[clocked_count] = g_PGC_raw_data[PGC_rawdata_index]
			--LS_API.DebugMsg("<ICSP>clocked_count: " .. clocked_count)
			clocked_count = clocked_count + 1
		end
		PGC_rawdata_index = PGC_rawdata_index + 2
	end
	--LS_API.DebugMsg("<ICSP>#g_PGC_data_clocked_table: " .. #g_PGC_data_clocked_table)

end
--------------------------------------------------------------------------------
-- OOD : get channel level by index, reserve for example - 2013.11.5
function get_PGD_bit_level( bit_index )
	local l_raw_data_index = g_PGD_raw_data_index;
	while l_raw_data_index <= #g_PGD_raw_data do
		if g_PGD_raw_data[l_raw_data_index] > bit_index then
			g_PGD_raw_data_index = l_raw_data_index - 2
			if g_PGD_raw_data[l_raw_data_index-1] > 0 then
				return true
			else
				return false
			end
		end
		l_raw_data_index = l_raw_data_index + 2
	end
	g_PGD_raw_data_index = #g_PGD_raw_data
	if g_PGD_raw_data[#g_PGD_raw_data] > 0 then
		return true
	else
		return false
	end
end
